package com.meida.module.bus.provider.service.impl;

import com.alibaba.fastjson.util.TypeUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.egzosn.pay.common.bean.RefundOrder;
import com.meida.common.base.entity.EntityMap;
import com.meida.common.base.utils.FlymeUtils;
import com.meida.common.constants.CommonConstants;
import com.meida.common.enums.PayStatusEnum;
import com.meida.common.mybatis.base.service.impl.BaseServiceImpl;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.mybatis.query.CriteriaQuery;
import com.meida.common.mybatis.query.CriteriaSave;
import com.meida.common.mybatis.query.CriteriaUpdate;
import com.meida.common.security.OpenHelper;
import com.meida.common.utils.*;
import com.meida.module.bus.client.constants.StudentQueueConstants;
import com.meida.module.bus.client.entity.*;
import com.meida.module.bus.client.enums.*;
import com.meida.module.bus.provider.mapper.BusOrderMapper;
import com.meida.module.bus.provider.service.*;
import com.meida.module.bus.provider.utils.MyDateUtils;
import com.meida.module.bus.provider.utils.MyUtils;
import com.meida.module.file.provider.service.SysFileService;
import com.meida.module.live.config.AgoraProperties;
import com.meida.module.live.io.agora.utils.RtmTokenBuilderUtil;
import com.meida.module.live.service.AgoraRoomsService;
import com.meida.module.marketing.client.entity.MkgCouponUser;
import com.meida.module.marketing.provider.service.CouponUserService;
import com.meida.module.pay.client.entity.PayBalance;
import com.meida.module.pay.client.entity.PayBalanceLog;
import com.meida.module.pay.client.entity.PayConfig;
import com.meida.module.pay.client.entity.PayInfo;
import com.meida.module.pay.provider.response.PayResponse;
import com.meida.module.pay.provider.service.PayBalanceLogService;
import com.meida.module.pay.provider.service.PayBalanceService;
import com.meida.module.pay.provider.service.PayConfigService;
import com.meida.module.pay.provider.service.PayInfoService;
import com.meida.module.push.provider.service.JPushService;
import com.meida.module.system.provider.service.SysExpireStrategyService;
import com.meida.module.user.client.entity.AppUser;
import com.meida.module.user.provider.service.AppUserService;
import com.meida.msg.client.entity.MsgReceive;
import com.meida.msg.provider.service.MsgReceiveService;
import com.meida.starter.rabbitmq.client.RabbitMqClient;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.*;

/**
 * 订单表接口实现类
 *
 * @author flyme
 * @date 2021-08-03
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class BusOrderServiceImpl extends BaseServiceImpl<BusOrderMapper, BusOrder> implements BusOrderService {

    @Autowired
    private BusSubjectService busSubjectService;

    @Autowired
    private BusTutorTypeService busTutorTypeService;

    @Autowired
    private SysFileService sysFileService;

    @Autowired
    private CouponUserService couponUserService;

    @Autowired
    private BusOrderAnswerService busOrderAnswerService;

    @Autowired
    private BusOrderQuestionService busOrderQuestionService;

    @Autowired
    private BusOrderAppraiseService busOrderAppraiseService;

    @Autowired
    private BusScholartyrantService busScholartyrantService;

    @Autowired
    private PayBalanceService payBalanceService;

    @Autowired
    private PayBalanceLogService payBalanceLogService;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private RtmTokenBuilderUtil rtmTokenBuilderUtil;

    @Autowired
    private AgoraProperties agoraProperties;

    @Autowired
    private MsgReceiveService msgReceiveService;

    @Autowired
    private AppUserService appUserService;

    @Autowired
    public RabbitMqClient rabbitMqClient;

    @Autowired
    private JPushService jPushService;

    @Autowired
    private AgoraRoomsService agoraRoomsService;

    @Autowired
    private PayInfoService payInfoService;

    @Autowired
    private BusAfterserviceService busAfterserviceService;

    @Autowired
    private SysExpireStrategyService sysExpireStrategyService;

    @Autowired
    private PayConfigService payConfigService;

    @Autowired
    private HttpServletRequest httpServletRequest;


    @Override
    public ResultBody beforeAdd(CriteriaSave cs, BusOrder order, EntityMap extra) {
        return ResultBody.ok();
    }


    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody beforePageList(CriteriaQuery<BusOrder> cq, BusOrder order, EntityMap requestMap) {
        cq.orderByDesc("busOrder.createTime");
        return ResultBody.ok();
    }


    @Override
    public ResultBody getWaitConfirmedInfo(Long orderId, Long couponUserId, Long answerId, BigDecimal rewardAmount) {
        //需要根据订单类型返回对应的确认订单信息
        EntityMap result = new EntityMap();
        Long userId = OpenHelper.getUserId();
        BusOrder busOrder = getById(orderId);
        if (FlymeUtils.isEmpty(busOrder)) {
            return ResultBody.failed("订单不存在");
        }
        Integer payState = busOrder.getPayState();
        if (PayStateEnum.HavePay.getValue().equals(payState)) {
            return ResultBody.failed("该订单已支付");
        }
        Integer orderType = busOrder.getOrderType();
        //专业ID
        Long subjectId = busOrder.getSubjectId();
        //知识标签
        String subjectIds = busOrder.getSubjectIds();
        String orderDescribe = busOrder.getOrderDescribe();
        result.put("orderId", busOrder.getOrderId());
        result.put("subjectIds", busOrder.getSubjectIds());
        result.put("durationTime", busOrder.getDurationTime());
        result.put("orderDescribe", orderDescribe);
        result.put("tutorTypeId", busOrder.getTutorTypeId());
        result.put("orderState", busOrder.getOrderState());
        result.put("answerUserId", busOrder.getAnswerUserId());
        String appointmentDate = busOrder.getAppointmentDate();
        String appointmentTime = busOrder.getAppointmentTime();
        if (OrderTypeEnum.TakePhotosAskQuestions.getValue() != orderType) {
            String targetTimezone = httpServletRequest.getHeader("targetTimezone");
            String appointmentDateTimeStr = appointmentDate + " " + appointmentTime + ":00";
            Date date = DateUtils.strToDate(appointmentDateTimeStr, "yyyy-MM-dd HH:mm:ss");
            Date newDate = MyDateUtils.convertTimezone(date, targetTimezone);
            String newAppointmentDate = DateUtils.formatDate(newDate, "yyyy-MM-dd");
            String newAppointmentTime = DateUtils.formatDate(newDate, "HH:mm");
            result.put("appointmentDate", newAppointmentDate);
            result.put("appointmentTime", newAppointmentTime);
        }
        //指定学霸下单
        Long answerUserId = busOrder.getAnswerUserId();

        //查询专业
        EntityMap subjectInfo = busSubjectService.getSimpleSubjectInfo(subjectId);
        //查询知识点
        List<String> subjectTitles = busSubjectService.selectSubjectTitles(subjectIds);
        result.putAll(subjectInfo);
        result.put("subjectTitles", subjectTitles);

        result.put("orderType", orderType);

        //订单金额
        BigDecimal amount = busOrder.getOrderAmount();

        PayBalance payBalance = payBalanceService.getByUserId(userId);
        if (FlymeUtils.isEmpty(payBalance)) {
            payBalance = new PayBalance();
        }
        //账户余额
        BigDecimal balanceAmount = FlymeUtils.getBigDecimal(payBalance.getBindAmount(), new BigDecimal("0"));
        //需充值金额
        BigDecimal rechargeAmount = new BigDecimal("0");


        //可使用优惠券数量
        Integer couponCanUseNum = couponUserService.countEnabledCoupon(userId, orderType, amount);
        result.put("couponCanUseNum", couponCanUseNum);
        //不可使用优惠券数量
        Integer couponCanNotUseNum = couponUserService.countDisabledCoupon(userId, orderType, amount);
        result.put("couponCanNotUseNum", couponCanNotUseNum);

        //订单初始金额
        BigDecimal orderAmount = new BigDecimal("0");
        switch (OrderTypeEnum.getByValue(orderType)) {
            //拍照提问
            case TakePhotosAskQuestions:
                List<Long> subjectIdList = MyUtils.stringToLongList(subjectIds);
                //orderAmount = subjectInfo.getBigDecimal("amount");
                orderAmount =busSubjectService.getPriceByIds(subjectIdList);
                break;
            //预约辅导
            case BookingTutoring:
                //根据辅导类型去计算订单金额
                //辅导类型
                Long tutorTypeId = busOrder.getTutorTypeId();
                //预约时长
                BigDecimal durationTime = busOrder.getDurationTime();
                BusTutorType busTutorType = busTutorTypeService.getById(tutorTypeId);
                //收费方式
                Integer chargeType = busTutorType.getChargeType();
                orderAmount = busTutorType.getTutorPrice();
                //如果收费方式是按时长则金额=单价*时长
                if (TutorChargeTypeEnum.Time.getValue().equals(chargeType)) {
                    orderAmount = orderAmount.multiply(durationTime).setScale(2, BigDecimal.ROUND_HALF_UP);
                }
                break;
            //作业无忧
            case HomeWork:
                BusOrderAnswer orderAnswer = busOrderAnswerService.getById(answerId);
                ApiAssert.isNotEmpty("answerId不能为空", orderAnswer);
                BigDecimal quotedPrice = orderAnswer.getQuotedPrice();
                orderAmount = quotedPrice;
                busOrder.setOrderAmount(quotedPrice);
                //最终报价
                result.put("quotedPrice", quotedPrice);
                break;
        }
        result.put("orderAmount", orderAmount);
        //应付金额
        BigDecimal payableAmount = orderAmount;

        //悬赏金额
        if (FlymeUtils.isEmpty(rewardAmount)) {
            rewardAmount = FlymeUtils.getBigDecimal(busOrder.getRewardAmount(), "0");
        }

        if (FlymeUtils.ge(rewardAmount, new BigDecimal("0"))) {
            //加上悬赏金额
            payableAmount = payableAmount.add(rewardAmount);
            //更新订单应付金额
            busOrder.setPayableAmount(payableAmount);
            busOrder.setRewardAmount(rewardAmount);

        }
        busOrder.setOrderNo(IdWorker.getIdStr());
        updateById(busOrder);
        result.put("orderNo", busOrder.getOrderNo());
        //计算折扣金额
        BigDecimal discountAmount = couponUserService.calculateDiscountAmountByCouponUserId(couponUserId, orderAmount);
        if (FlymeUtils.isNotEmpty(discountAmount) && FlymeUtils.gtzero(discountAmount)) {
            //减去折扣金额
            payableAmount = payableAmount.subtract(discountAmount);
        }

        //计算需要充值的金额
        if (FlymeUtils.gt(payableAmount, balanceAmount)) {
            rechargeAmount = payableAmount.subtract(balanceAmount);
        }
        commonGetOrderDetails(result);
        result.put("balanceAmount", balanceAmount);
        result.put("rechargeAmount", rechargeAmount);
        result.put("rewardAmount", rewardAmount);
        result.put("payableAmount", payableAmount);
        result.put("discountAmount", discountAmount);
        return ResultBody.ok(result);
    }


    @Override
    public ResultBody orderPaySuccess(String outTradeNo, String payType, Long couponUserId, Long answerId, BigDecimal payableAmount, BigDecimal discountAmount) {
        log.info("支付成功回调orderPaySuccess--------------------------" + outTradeNo);
        BusOrder busOrder = findByOrderNo(outTradeNo);
        Long orderId = busOrder.getOrderId();
        busOrder.setPayType(payType);
        busOrder.setPayState(PayStateEnum.HavePay.getValue());
        busOrder.setPayTime(DateUtils.getDateTime());
        busOrder.setCouponUserId(couponUserId);
        busOrder.setPayableAmount(payableAmount);
        busOrder.setDiscountAmount(discountAmount);
        Integer orderType = busOrder.getOrderType();
        switch (OrderTypeEnum.getByValue(orderType)) {
            //拍照提问
            case TakePhotosAskQuestions:
                //修改订单状态待接单
                busOrder.setOrderState(OrderStatePEnum.OrderState1.getValue());
                break;
            //预约辅导
            case BookingTutoring:
                //修改订单状态待接单
                busOrder.setOrderState(OrderStateYEnum.OrderState1.getValue());
                break;
            //作业无忧
            case HomeWork:
                //接受
                BusOrderAnswer busOrderAnswer = busOrderAnswerService.getById(answerId);
                Long answerUserId = busOrderAnswer.getAnswerUserId();
                //设置为答案
                if (FlymeUtils.isNotEmpty(answerId)) {
                    busOrderAnswerService.setIsAnswer(answerId);
                }
                if (FlymeUtils.isNotEmpty(answerUserId)) {
                    //全局配置
                    //全局配置
                    EntityMap config = redisUtils.getConfigMap("SERVICE_FEE_CONFIG");
                    //佣金比例
                    BigDecimal platformServiceFee = config.getBigDecimal("platformServiceFee");
                    BigDecimal commissionRate = new BigDecimal(0.2);
                    if (FlymeUtils.isNotEmpty(platformServiceFee)) {
                        commissionRate = platformServiceFee.divide(new BigDecimal(100));
                    }
                    BigDecimal orderAmount = busOrder.getOrderAmount();
                    BigDecimal rewardAmount = FlymeUtils.getBigDecimal(busOrder.getRewardAmount(), "0");
                    //计算佣金金额(订单金额+悬赏金额)*(1-佣金比例)
                    BigDecimal commission = orderAmount.add(rewardAmount).multiply(BigDecimal.ONE.subtract(commissionRate));
                    busOrder.setCommission(commission);
                    busOrder.setAnswerUserId(answerUserId);
                    //修改订单状态为待解答
                    busOrder.setOrderState(OrderStateZEnum.OrderState2.getValue());
                    break;

                }

        }
        Boolean updated = updateById(busOrder);
        if (FlymeUtils.isNotEmpty(couponUserId) && updated) {
            //更新优惠券为已使用状态
            couponUserService.updateCouponState(orderId, couponUserId.toString(), CommonConstants.ENABLED);
        }
        log.info("支付成功回调orderPaySuccess--------------------------订单更新" + outTradeNo);
        if (updated) {
            Long userId = busOrder.getUserId();
            //处理订单节点通知--->用户
            orderPaySuccessNoticeToUser(userId, orderType);
            //处理订单节点延时通知--->学霸跟用户(预约辅导预约时间提前20分钟通知)
            orderPaySuccessNoticeToAllUser(busOrder);
            log.info("支付成功回调orderPaySuccess--------------------------发送消息" + outTradeNo);
        }
        return ResultBody.ok();
    }

    private void orderPaySuccessNoticeToUser(Long userId, Integer orderType) {
        OrderTypeEnum orderTypeEnum = OrderTypeEnum.getByValue(orderType);
        String orderTypeDesc = orderTypeEnum.getLabel();
        String msgTitle = orderTypeDesc + "付费成功通知";
        String msgContent = "恭喜您！您的" + orderTypeDesc + "已支付成功，等待学霸接单！感谢您使用留同学APP";
        MsgReceive msgReceive = msgReceiveService.sendMsgReceiveNotice(BusOrder.class.getSimpleName(), userId, msgTitle, msgContent);
        orderPushMessage(msgReceive, msgTitle, msgContent);
    }

    private void orderPaySuccessNoticeToAllUser(BusOrder busOrder) {
        Integer orderType = busOrder.getOrderType();
        OrderTypeEnum orderTypeEnum = OrderTypeEnum.getByValue(orderType);
        Long orderId = busOrder.getOrderId();
        //预约辅导上课通知
        if (orderTypeEnum.BookingTutoring.getValue().equals(orderType)) {
            String appointmentDate = busOrder.getAppointmentDate();
            String appointmentTime = busOrder.getAppointmentTime();
            String appointmentTimeStr = appointmentDate + " " + appointmentTime + ":00";
            Date date = DateUtils.strToDate(appointmentTimeStr, "yyyy-MM-dd HH:mm:ss");
            Date expireTime = MyDateUtils.addMin(date, -20);
            String redisKey = RedisKeyEnum.OrderNotice.getRedisKey() + orderId;
            sysExpireStrategyService.saveAndToRedis(redisKey, orderId, RedisKeyEnum.OrderNotice.getRedisTargetType(), expireTime);
        }
    }

    @Override
    public Long countFinshOrderNum(Long answerUserId) {
        CriteriaQuery cq = new CriteriaQuery(BusOrder.class);
        cq.eq("answerUserId", answerUserId);
        cq.eq("orderState", OrderStatePEnum.OrderState3.getValue());
        return count(cq);
    }

    @Override
    public Integer countAllUserOrderNum(Long answerUserId) {
        CriteriaQuery cq = new CriteriaQuery(BusOrder.class);
        cq.select("COALESCE(COUNT(DISTINCT userId),0) allUserOrderNum");
        cq.eq("answerUserId", answerUserId);
        cq.eq("orderState", OrderStatePEnum.OrderState3.getValue());
        EntityMap entityMap = findOne(cq);
        return entityMap.getInt("allUserOrderNum");
    }

    @Override
    public Integer countAgainUserOrderNum(Long answerUserId) {
        CriteriaQuery cq = new CriteriaQuery(BusOrder.class);
        cq.select("COALESCE(COUNT(DISTINCT userId),0) againUserOrderNum");
        cq.eq("answerUserId", answerUserId);
        cq.eq("orderState", OrderStatePEnum.OrderState3.getValue());
        cq.having("COUNT(userId)", 1);
        EntityMap entityMap = findOne(cq);
        return entityMap.getInt("againUserOrderNum");
    }

    @Override
    public Map getOrderStateDesc(Integer orderType, String orderState) {
        Map map = new HashMap();
        String orderStateText = "";
        String orderTypeText = "";
        if (OrderTypeEnum.TakePhotosAskQuestions.getValue() == orderType) {
            OrderStatePEnum orderStateEnum = OrderStatePEnum.getByValue(orderState);
            orderTypeText = OrderTypeEnum.TakePhotosAskQuestions.getLabel();
            if (FlymeUtils.isNotEmpty(orderStateEnum)) {
                orderStateText = orderStateEnum.getLabel();
            }
        }
        if (OrderTypeEnum.BookingTutoring.getValue() == orderType) {
            OrderStateYEnum orderStateEnum = OrderStateYEnum.getByValue(orderState);
            orderTypeText = OrderTypeEnum.BookingTutoring.getLabel();
            if (FlymeUtils.isNotEmpty(orderStateEnum)) {
                orderStateText = orderStateEnum.getLabel();
            }
        }
        if (OrderTypeEnum.HomeWork.getValue() == orderType) {
            OrderStateZEnum orderStateEnum = OrderStateZEnum.getByValue(orderState);
            orderTypeText = OrderTypeEnum.HomeWork.getLabel();
            if (FlymeUtils.isNotEmpty(orderStateEnum)) {
                orderStateText = orderStateEnum.getLabel();
            }
        }
        map.put("orderStateText", orderStateText);
        map.put("orderTypeText", orderTypeText);
        return map;
    }

    @Override
    public EntityMap convertOrderState(Long orderId, Integer orderType, String orderState) {
        EntityMap data = new EntityMap();
        data.put("orderStateDesc", "");
        data.put("btnId", "");
        data.put("btnName", "");
        if (OrderTypeEnum.TakePhotosAskQuestions.getValue() == orderType) {
            OrderStatePEnum orderStatePEnum = OrderStatePEnum.getByValue(orderState);
            if (FlymeUtils.isNotEmpty(orderStatePEnum)) {
                data.put("orderStateDesc", orderStatePEnum.getLabel());
                data.put("btnId", orderStatePEnum.getBtnId());
                data.put("btnName", orderStatePEnum.getBtnName());
                if (OrderStatePEnum.OrderState5.getValue().equals(orderState)) {
                    convertOrderAppraise(data, orderId);
                }
            }
        }
        if (OrderTypeEnum.BookingTutoring.getValue() == orderType) {
            OrderStateYEnum orderStateYEnum = OrderStateYEnum.getByValue(orderState);
            if (FlymeUtils.isNotEmpty(orderStateYEnum)) {
                data.put("orderStateDesc", orderStateYEnum.getLabel());
                data.put("btnId", orderStateYEnum.getBtnId());
                data.put("btnName", orderStateYEnum.getBtnName());
                if (orderStateYEnum.OrderState5.getValue().equals(orderState)) {
                    convertOrderAppraise(data, orderId);
                }
            }
        }
        if (OrderTypeEnum.HomeWork.getValue() == orderType) {
            OrderStateZEnum orderStateEnum = OrderStateZEnum.getByValue(orderState);
            if (FlymeUtils.isNotEmpty(orderStateEnum)) {
                data.put("orderStateDesc", orderStateEnum.getLabel());
                data.put("btnId", orderStateEnum.getBtnId());
                data.put("btnName", orderStateEnum.getBtnName());
                if (orderStateEnum.OrderState5.getValue().equals(orderState)) {
                    convertOrderAppraise(data, orderId);
                }
            }
        }
        return data;
    }

    private void convertOrderAppraise(EntityMap data, Long orderId) {
        //统计订单是否评价
        Long num = busOrderAppraiseService.countNumByOrderId(orderId);
        if (num > 0) {
            data.put("btnId", "lookAppraise");
            data.put("btnName", "查看评价");
        }
    }

    @Override
    public Map getOrderStateDesc1(Long orderId, Integer orderType, String orderState, Long answerUserId, Integer answerState) {
        Map map = getOrderStateDesc(orderType, orderState);
        if (!orderState.equals("5") && !orderState.equals("6") && !orderState.equals("7")) {
            if (OrderTypeEnum.TakePhotosAskQuestions.getValue() == orderType) {
                if (OrderStatePEnum.OrderState3.getValue().equals(orderState) || OrderStatePEnum.OrderState4.getValue().equals(orderState)) {
                    AnswerStateEnum answerStateEnum = AnswerStateEnum.getByValue(answerState);
                    if (FlymeUtils.isNotEmpty(answerStateEnum)) {
                        map.put("orderStateText", answerStateEnum.getLabel());
                    }
                }
            }
            if (OrderTypeEnum.BookingTutoring.getValue() == orderType) {
                if (OrderStateYEnum.OrderState5.getValue().equals(orderState)) {
                    AnswerStateEnum answerStateEnum = AnswerStateEnum.getByValue(answerState);
                    if (FlymeUtils.isNotEmpty(answerStateEnum)) {
                        map.put("orderStateText", answerStateEnum.getLabel());
                    }
                }
            }
            if (OrderTypeEnum.HomeWork.getValue() == orderType) {
                if (OrderStateZEnum.OrderState1.getValue().equals(orderState)) {
                    Long num = busOrderAnswerService.countNumByOrderIdAndUserId(orderId, answerUserId);
                    if (num > 0) {
                        map.put("orderStateText", "已出价");
                    }
                }
                if (OrderStateZEnum.OrderState3.getValue().equals(orderState) || OrderStateZEnum.OrderState4.getValue().equals(orderState)) {
                    AnswerStateEnum answerStateEnum = AnswerStateEnum.getByValue(answerState);
                    if (FlymeUtils.isNotEmpty(answerStateEnum)) {
                        map.put("orderStateText", answerStateEnum.getLabel());
                    }
                }
            }
        }

        return map;
    }

    @Override
    public String getOrderTypeDesc(Integer orderType) {
        String orderTypeDesc = "";
        OrderTypeEnum orderTypeEnum = OrderTypeEnum.getByValue(orderType);
        if (FlymeUtils.isNotEmpty(orderTypeEnum)) {
            orderTypeDesc = orderTypeEnum.getLabel();
        }
        return orderTypeDesc;
    }

    @Override
    public ResultBody receiveOrderQuestion(Long orderId) {
        ApiAssert.allNotNull("缺少订单Id", orderId);
        RLock lock = redisLock.lock(orderId);
        //加锁避免并发问题
        try {
            BusOrder busOrder = getById(orderId);
            if (FlymeUtils.isEmpty(busOrder)) {
                return ResultBody.failed("订单不存在");
            }
            Integer payState = busOrder.getPayState();
            if (PayStateEnum.NoPay.getValue() == payState) {
                return ResultBody.failed("该订单未支付");
            }
            Long userId = OpenHelper.getUserId();
//            Long answerUserId = busOrder.getAnswerUserId();
//            if (FlymeUtils.isNotEmpty(answerUserId)) {
//                if (userId.longValue() == answerUserId.longValue()) {
//                    return ResultBody.failed("你已领取该题目");
//                } else {
//                    return ResultBody.failed("该题目已被领取");
//                }
//            }
            Integer orderType = busOrder.getOrderType();
            if (OrderTypeEnum.TakePhotosAskQuestions.getValue() != orderType) {
                return ResultBody.failed("只有拍照提问类型的订单才能领取题目");
            }
            CriteriaUpdate cu = new CriteriaUpdate();
            cu.eq("orderId", orderId);
            cu.set("answerUserId", userId);
            cu.set("orderState", OrderStatePEnum.OrderState2.getValue());
            boolean update = update(cu);
            if (update) {
                busOrder.setOrderState(OrderStatePEnum.OrderState2.getValue());
                //生成一条答题记录
                BusOrderAnswer busOrderAnswer = new BusOrderAnswer();
                busOrderAnswer.setOrderId(orderId);
                busOrderAnswer.setAnswerUserId(userId);
                busOrderAnswer.setIsAnswer(1);
                busOrderAnswer.setIsSettle(0);
                busOrderAnswer.setAnswerState(AnswerStateEnum.waitCheck.getValue());
                busOrderAnswerService.save(busOrderAnswer);
                //处理订单节点通知
                String msgTitle = "拍照提问接单成功通知";
                String msgContent = "恭喜您！您的拍照提问学霸已接单！感谢您使用留同学APP";
                Long orderUserId = busOrder.getUserId();
                MsgReceive msgReceive = msgReceiveService.sendMsgReceiveNotice(BusOrder.class.getSimpleName(), orderUserId, msgTitle, msgContent);
                orderPushMessage(msgReceive, msgTitle, msgContent);
                return ResultBody.ok(busOrder).setMsg("领取题目成功");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            redisLock.unlock(lock);
        }
        return ResultBody.failed("领取题目失败");
    }

    @Override
    public ResultBody offerPriceList(Long orderId) {
        ApiAssert.allNotNull("缺少orderId参数", orderId);
        CriteriaQuery cq = new CriteriaQuery(BusOrder.class);
        cq.select(BusOrder.class, "orderId", "orderNo", "orderType", "subjectIds", "orderDescribe", "createTime");
        cq.select(BusSubject.class, "subjectTitle");
        cq.eq(BusOrder.class, "orderId", orderId);
        cq.createJoin(BusSubject.class).setMainField("subjectId").setJoinField("subjectId");
        EntityMap orderInfo = findOne(cq);
        if (FlymeUtils.isEmpty(orderInfo)) {
            return ResultBody.failed("订单不存在");
        }
        String subjectIds = orderInfo.get("subjectIds");
        List<String> subjectTitles = busSubjectService.selectSubjectTitles(subjectIds);
        orderInfo.put("subjectTitles", subjectTitles);
        EntityMap data = new EntityMap();
        data.put("orderInfo", orderInfo);
        //todo 查询出价列表
        List<EntityMap> homeWorkOrderAnswerList = busOrderAnswerService.selectHomeWorkOrderAnswerList(orderId);
        if (FlymeUtils.isNotEmpty(homeWorkOrderAnswerList)) {
            for (EntityMap entityMap : homeWorkOrderAnswerList) {
                //解答人Id
                Long answerUserId = entityMap.getLong("answerUserId");
                EntityMap result = busOrderAppraiseService.getTotalScoreInfo(answerUserId);
                BigDecimal totalScore = FlymeUtils.getBigDecimal(result.getBigDecimal("totalScore"), "0").setScale(1);
                result.put("totalScore", totalScore.toString());
                entityMap.putAll(result);
            }
        }
        data.put("homeWorkOrderAnswerList", homeWorkOrderAnswerList);
        return ResultBody.ok(data);
    }

    @Override
    public ResultBody updateOfferPrice(BusOrderAnswer busOrderAnswer) {
        Long orderId = busOrderAnswer.getOrderId();
        Long userId = OpenHelper.getUserId();
        BusOrder busOrder = getById(orderId);
        ApiAssert.isNotEmpty("订单不存在", busOrder);
        Integer orderType = busOrder.getOrderType();
        Date createTime = busOrder.getCreateTime();
        if (OrderTypeEnum.HomeWork.getValue() != orderType) {
            return ResultBody.failed("只有作业无忧类型的订单才能出价");
        }

        Long answerUserId = busOrder.getAnswerUserId();

        //非指定模式
        if (FlymeUtils.isEmpty(answerUserId)) {
            BigDecimal quotedPrice = busOrderAnswer.getQuotedPrice();
            ApiAssert.allNotNull("缺少出价参数", orderId, quotedPrice);
            String orderState = busOrder.getOrderState();
            if (!orderState.equals(OrderStateZEnum.OrderState1.getValue())) {
                return ResultBody.failed("该订单已完成报价");
            }
            //获取作业无忧报价设置
            EntityMap quotedPriceMap = redisUtils.getConfigMap("QUOTED_PRICE");
            //最多报价人数
            Integer quotedNum = quotedPriceMap.getInt("quotedNum");
            //报价时长
            Integer quotedHours = quotedPriceMap.getInt("quotedHours");
            Date endDateTime = MyDateUtils.addHours(createTime, quotedHours);
            Date nowDateTime = DateUtils.getNowDateTime();
            String endDateTimeStr = DateUtils.formatDateTime(endDateTime);
            String nowDateTimeStr = DateUtils.formatDateTime(nowDateTime);
            Boolean isGt = DateUtils.gt(nowDateTimeStr, endDateTimeStr);
            if (isGt) {
                return ResultBody.failed("该订单报价已结束");
            }
            Long num = busOrderAnswerService.countNumByOrderId(orderId);
            if (num > quotedNum) {
                return ResultBody.failed("该订单报价已满员");
            }
            busOrderAnswer.setIsSettle(0);
            busOrderAnswer.setAnswerUserId(OpenHelper.getUserId());
            busOrderAnswer.setAnswerState(0);
            Boolean save = busOrderAnswerService.saveOrUpdate(busOrderAnswer);
            if (save) {
                String msgTitle = "作业无忧学霸报价通知";
                String msgContent = "恭喜您！您的作业无忧已有学霸进行报价，请及时查看！感谢您使用留同学APP";
                MsgReceive msgReceive = msgReceiveService.sendMsgReceiveNotice(BusOrder.class.getSimpleName(), busOrder.getUserId(), msgTitle, msgContent);
                orderPushMessage(msgReceive, msgTitle, msgContent);
                return ResultBody.ok().setMsg("报价成功");
            }
        } else {
            if (answerUserId.equals(userId)) {
                BigDecimal expectedAmount = busOrder.getExpectedAmount();
                busOrderAnswer.setQuotedPrice(expectedAmount);
                busOrderAnswer.setBargainPrice(expectedAmount);
                busOrderAnswer.setIsSettle(0);
                busOrderAnswer.setAnswerUserId(userId);
                busOrderAnswer.setAnswerState(0);
                //标记为已领取
                busOrderAnswer.setReceiveState(1);
                Boolean save = busOrderAnswerService.saveOrUpdate(busOrderAnswer);
                if (save) {
                    String msgTitle = "作业无忧学霸接单通知";
                    String msgContent = "恭喜您！您的作业无忧已被学霸接单 ，请及时支付订单！感谢您使用留同学APP";
                    MsgReceive msgReceive = msgReceiveService.sendMsgReceiveNotice(BusOrder.class.getSimpleName(), busOrder.getUserId(), msgTitle, msgContent);
                    orderPushMessage(msgReceive, msgTitle, msgContent);
                    return ResultBody.ok().setMsg("报价成功");
                }
            }
        }

        return ResultBody.failed("报价失败");
    }


    @Override
    public ResultBody acceptAppointment(Map params) {
        Long orderId = TypeUtils.castToLong(params.get("orderId"));
        ApiAssert.allNotNull("缺少订单参数", orderId);
        BusOrder busOrder = getById(orderId);
        if (FlymeUtils.isEmpty(busOrder)) {
            return ResultBody.failed("订单不存在");
        }
        String appointmentDate = busOrder.getAppointmentDate();
        String appointmentTime = busOrder.getAppointmentTime();
        String appointmentDateTime = appointmentDate + " " + appointmentTime + ":00";
        String nowDateTime = DateUtils.getDateTime();
        Boolean gt = DateUtils.gt(nowDateTime, appointmentDateTime);
        if (gt) {
            return ResultBody.failed("已过预约时间,不能接单");
        }
        Integer payState = busOrder.getPayState();
        if (PayStateEnum.NoPay.getValue() == payState) {
            return ResultBody.failed("该订单未支付");
        }
        Integer orderType = busOrder.getOrderType();
        if (OrderTypeEnum.BookingTutoring.getValue() != orderType) {
            return ResultBody.failed("只有辅导预约类型的订单才能接受预约");
        }
        String orderState = busOrder.getOrderState();
        if (!orderState.equals(OrderStateYEnum.OrderState1.getValue())) {
            return ResultBody.failed("该订单已被预约");
        }
        Long answerUserId = OpenHelper.getUserId();
        RLock lock = redisLock.lock(orderId);
        try {
            CriteriaUpdate cu = new CriteriaUpdate();
            cu.eq("orderId", orderId);
            cu.set("orderState", OrderStateYEnum.OrderState2.getValue());
            cu.set("answerUserId", answerUserId);
            boolean update = update(cu);
            if (update) {
                //生成一条答题记录
                BusOrderAnswer busOrderAnswer = new BusOrderAnswer();
                busOrderAnswer.setOrderId(orderId);
                busOrderAnswer.setAnswerUserId(answerUserId);
                busOrderAnswer.setIsAnswer(1);
                busOrderAnswer.setIsSettle(0);
                busOrderAnswer.setAnswerState(AnswerStateEnum.waitCheck.getValue());
                busOrderAnswerService.save(busOrderAnswer);
                String msgTitle = "预约辅导接单成功通知";
                String msgContent = "恭喜您！您的预约辅导学霸已接单！请按预约的时间进行上课，感谢您使用留同学APP";
                Long orderUserId = busOrder.getUserId();
                MsgReceive msgReceive = msgReceiveService.sendMsgReceiveNotice(BusOrder.class.getSimpleName(), orderUserId, msgTitle, msgContent);
                orderPushMessage(msgReceive, msgTitle, msgContent);



                Date expireTime = DateUtils.strToDate(appointmentDateTime, "yyyy-MM-dd HH:mm:ss");
                String redisKey = RedisKeyEnum.OrderCsCancel.getRedisKey() + orderId;
                sysExpireStrategyService.saveAndToRedis(redisKey, orderId, RedisKeyEnum.OrderCsCancel.getRedisTargetType(), DateUtils.addMilliseconds(expireTime,20));

                return ResultBody.ok().setMsg("接受预约成功");
            }
        } finally {
            redisLock.unlock(lock);
        }
        return ResultBody.failed("接受预约失败");
    }

    @Override
    public ResultBody askQuestion(Map params) {
        return busOrderQuestionService.add(params);
    }

    @Override
    public ResultBody getAfterService(Map params) {
        Long orderId = TypeUtils.castToLong(params.get("orderId"));
        if (FlymeUtils.isEmpty(orderId)) {
            return ResultBody.failed("缺少订单参数");
        }
        BusOrder busOrder = getById(orderId);
        if (FlymeUtils.isEmpty(busOrder)) {
            return ResultBody.failed("该订单不存在");
        }
        CriteriaQuery cq = new CriteriaQuery(BusOrder.class);
        cq.select(BusOrder.class, "orderId", "orderNo", "orderType", "coverImg", "orderAmount", "subjectId", "payableAmount", "subjectIds", "orderDescribe", "createTime");
        cq.select(BusSubject.class, "subjectTitle");
        cq.eq(BusOrder.class, "orderId", orderId);
        cq.createJoin(BusSubject.class).setMainField("subjectId").setJoinField("subjectId");
        EntityMap orderInfo = findOne(cq);
        String subjectIds = orderInfo.get("subjectIds");
        Integer orderType = orderInfo.getInt("orderType");
        List<String> subjectTitles = busSubjectService.selectSubjectTitles(subjectIds);
        orderInfo.put("subjectTitles", subjectTitles);
        String orderTypeDesc = getOrderTypeDesc(orderType);
        orderInfo.put("orderTypeDesc", orderTypeDesc);
        EntityMap data = new EntityMap();
        data.put("orderInfo", orderInfo);
        //todo 查询退款信息
        PayBalanceLog payBalanceLog = payBalanceLogService.findByBusIdAndType(orderId, BalanceLogTypeEnum.logType4.getValue());
        data.put("payBalanceLog", payBalanceLog);
        PayInfo payInfo = payInfoService.getByProperty("busId", orderId);
        BusAfterservice afterservice = busAfterserviceService.getByOrderId(orderId);
        data.put("payInfo", payInfo);
        data.put("afterservice", afterservice);
        return ResultBody.ok(data);
    }

    @Override
    public ResultBody getOrderAppraise(Map params) {
        Long orderId = TypeUtils.castToLong(params.get("orderId"));
        ApiAssert.allNotNull("缺少订单参数", orderId);
        BusOrder busOrder = getById(orderId);
        if (FlymeUtils.isEmpty(busOrder)) {
            return ResultBody.failed("订单不存在");
        }
        Long answerUserId = busOrder.getAnswerUserId();
        EntityMap scholarTyrantInfo = busScholartyrantService.getScholartyrantInfo(answerUserId);
        EntityMap data = new EntityMap();
        data.put("scholarTyrantInfo", scholarTyrantInfo);
        EntityMap orderAppraiseInfo = busOrderAppraiseService.getOrderAppraiseInfo(orderId);
        data.put("orderAppraiseInfo", orderAppraiseInfo);
        return ResultBody.ok(data);
    }

    @Override
    public ResultBody updateBargainPrice(Map params) {
        Long answerId = TypeUtils.castToLong(params.get("answerId"));
        BigDecimal bargainPrice = TypeUtils.castToBigDecimal(params.get("bargainPrice"));
        ApiAssert.allNotNull("缺少必要参数", answerId, bargainPrice);
        BusOrderAnswer busOrderAnswer = busOrderAnswerService.getById(answerId);
        if (FlymeUtils.isEmpty(busOrderAnswer)) {
            return ResultBody.failed("该出价信息不存在");
        }
        busOrderAnswer.setBargainPrice(bargainPrice);
        boolean result = busOrderAnswerService.updateById(busOrderAnswer);
        if (result) {
            Long orderId = busOrderAnswer.getOrderId();
            BusOrder busOrder = getById(orderId);
            String msgTitle = "作业无忧学霸还价通知";
            String msgContent = "恭喜您！您的作业无忧已有学霸进行还价，请及时查看！感谢您使用留同学APP";
            MsgReceive msgReceive = msgReceiveService.sendMsgReceiveNotice(BusOrder.class.getSimpleName(), busOrder.getUserId(), msgTitle, msgContent);
            orderPushMessage(msgReceive, msgTitle, msgContent);
            return ResultBody.ok().setMsg("报价成功");
        }
        return ResultBody.ok().setMsg("还价成功");
    }

    @Override
    public Long totalReceiveOrderNum(Long answerUserId) {
        ApiAssert.isNotEmpty("缺少userId参数", answerUserId);
        CriteriaQuery cq = new CriteriaQuery(BusOrder.class);
        cq.eq("answerUserId", answerUserId);
        cq.ne("orderState", 0);
        return count(cq);
    }

    @Override
    public ResultBody refuseOrder(Long orderId) {
        if (FlymeUtils.isEmpty(orderId)) {
            return ResultBody.failed("缺少订单参数");
        }
        BusOrder busOrder = getById(orderId);
        if (FlymeUtils.isEmpty(busOrder)) {
            return ResultBody.failed("该订单不存在");
        }
        Long answerUserId = busOrder.getAnswerUserId();
        if (FlymeUtils.isEmpty(answerUserId)) {
            return ResultBody.failed("该订单未指定学霸下单");
        }
        Integer payState = busOrder.getPayState();
        if (PayStateEnum.NoPay.getValue() == payState) {
            return ResultBody.failed("该订单未付款");
        }
        CriteriaUpdate cu = new CriteriaUpdate();
        cu.eq("orderId", orderId);
        cu.set("orderState", 0);
        boolean update = update(cu);
        if (update) {
            Long userId = busOrder.getUserId();
            String orderNo = busOrder.getOrderNo();
            BigDecimal payableAmount = busOrder.getPayableAmount();
            if (FlymeUtils.gt(payableAmount, BigDecimal.ZERO)) {
                String title = "订单支付金额退回";
                String body = "学霸拒接订单,订单支付金额已原路退回";
                payBalanceService.addBalance(userId, "", payableAmount, orderNo, BalanceLogTypeEnum.logType5.getValue(), orderId, title, body);
                //todo 需不需要处理售后(往售后表插入数据)
                //退回优惠券
                Long couponUserId = busOrder.getCouponUserId();
                if (FlymeUtils.isNotEmpty(couponUserId)) {
                    MkgCouponUser mkgCouponUser = couponUserService.getById(couponUserId);
                    mkgCouponUser.setUseState(0);
                    couponUserService.updateById(mkgCouponUser);
                }
            }
            return ResultBody.ok("拒单成功");
        }
        return ResultBody.failed("拒单失败");
    }

    @Override
    public ResultBody answerIng(Long orderId) {
        if (FlymeUtils.isEmpty(orderId)) {
            return ResultBody.failed("缺少订单参数");
        }
        BusOrder busOrder = getById(orderId);
        if (FlymeUtils.isEmpty(busOrder)) {
            return ResultBody.failed("该订单不存在");
        }
        Integer orderType = busOrder.getOrderType();
        String orderState = busOrder.getOrderState();
        Boolean tag = false;
        switch (OrderTypeEnum.getByValue(orderType)) {
            //拍照提问
            case TakePhotosAskQuestions:
                if (OrderStatePEnum.OrderState2.getValue().equals(orderState)) {
                    busOrder.setOrderState(OrderStatePEnum.OrderState3.getValue());
                    tag = true;
                }
                break;
            //预约辅导
            case BookingTutoring:
                if (OrderStateYEnum.OrderState2.getValue().equals(orderState)) {
                    busOrder.setOrderState(OrderStateYEnum.OrderState3.getValue());
                    tag = true;
                }
                break;
            //作业无忧
            case HomeWork:
                if (OrderStateZEnum.OrderState2.getValue().equals(orderState)) {
                    busOrder.setOrderState(OrderStateZEnum.OrderState3.getValue());
                    tag = true;
                }
                break;
        }
        if (tag) {
            updateById(busOrder);
        }
        return ResultBody.ok(busOrder);
    }

    @Override
    public ResultBody deleteById(Long orderId) {
        BusOrder busOrder = getById(orderId);
        String orderState = busOrder.getOrderState();
        String info = "删除成功";
        if (orderState.equals("-1")) {
            //删除文件
            sysFileService.deleteByBusId(orderId);
            removeById(orderId);
        } else {
            CriteriaUpdate cu = new CriteriaUpdate();
            cu.eq("orderId", orderId);
            if (orderState.equals("P1") || orderState.equals("Z1") || orderState.equals("Y1")) {
                Long couponUserId = busOrder.getCouponUserId();
                if (busOrder.getPayState().equals(PayStateEnum.HavePay.getValue())) {
                    //调用退款逻辑
                    orderBookingTutoringCancel(busOrder, "取消订单", "客户取消订单");
                }
                if (FlymeUtils.isNotEmpty(couponUserId)) {
                    MkgCouponUser mkgCouponUser = couponUserService.getById(couponUserId);
                    mkgCouponUser.setUseState(0);
                    couponUserService.updateById(mkgCouponUser);
                }
                cu.set("orderState", 0);
                info = "取消成功";
            } else {
                cu.set("deleted", 1);
            }
            boolean update = update(cu);
        }

        return ResultBody.ok(info);
    }

    @Override
    public ResultBody refuseAnswer(Long orderId) {
        CriteriaUpdate cu = new CriteriaUpdate();
        cu.set(true, "answerUserId", null);
        cu.set(true, "privateOrder", 0);
        cu.eq(true, "orderId", orderId);
        update(cu);
        return ResultBody.ok("操作成功");
    }

    @Override
    public ResultBody closeLive(Long orderId, Long answerId) {
        updateOrderState(orderId, OrderStateYEnum.OrderState5.getValue());
        agoraRoomsService.setRoomsState(orderId.toString(), 2);
        //更新作业无忧审核状态
        CriteriaUpdate cu = new CriteriaUpdate();
        cu.set("answerState", 2);
        cu.eq(true, "answerId", answerId);
        busOrderAnswerService.update(cu);
        return ResultBody.msg("关闭成功");
    }

    @Override
    public ResultBody acceptAnswer(Long answerId) {
        if (FlymeUtils.isEmpty(answerId)) {
            return ResultBody.failed("缺少answerId参数");
        }
        BusOrderAnswer busOrderAnswer = busOrderAnswerService.getById(answerId);
        if (FlymeUtils.isEmpty(busOrderAnswer)) {
            return ResultBody.failed("订单答案不存在");
        }
        Integer answerState = busOrderAnswer.getAnswerState();
        if (AnswerStateEnum.checkPass.getValue() != answerState) {
            return ResultBody.failed("只有答案审核通过才能接受答案");
        }
        Long orderId = busOrderAnswer.getOrderId();
        BusOrder busOrder = getById(orderId);
        if (FlymeUtils.isEmpty(busOrder)) {
            return ResultBody.failed("该订单不存在");
        }
        busOrder.setOrderState("5");
        updateById(busOrder);
        //2.n天打款到学霸余额(redis 过期通知)
        String redisKey = RedisKeyEnum.OrderAnswerId.getRedisKey() + answerId;
        System.out.println("redisKey-----------" + redisKey);
        EntityMap settleConfig = redisUtils.getConfigMap("SETTLE_CONFIG");
        if (FlymeUtils.isNotEmpty(settleConfig)) {
            Integer orderType = busOrder.getOrderType();
            Long userId = busOrder.getUserId();
            //订单节点通知--->用户
            acceptAnswerSendUserMessage(orderType, userId);
            Long answerUserId = busOrder.getAnswerUserId();
            //订单节点通知--->学霸
            acceptAnswerSendAnswerUserMessage(orderType, answerUserId, userId);
            //取接受答案的参数配置
            Integer acceptAnswerDay = settleConfig.getInt("acceptAnswerDay");
            //设置订单答案结算截止日期
            Date settleExpireTime = DateUtils.plusDateDays(DateUtils.getNowDate(), acceptAnswerDay);
            busOrderAnswer.setSettleExpireTime(settleExpireTime);
            busOrderAnswerService.updateById(busOrderAnswer);
            sysExpireStrategyService.saveAndToRedis(redisKey, answerId, RedisKeyEnum.OrderAnswerId.getRedisTargetType(), settleExpireTime);
        }
        return ResultBody.ok("接受答案成功", busOrder);
    }

    private void acceptAnswerSendUserMessage(Integer orderType, Long userId) {
        if (OrderTypeEnum.TakePhotosAskQuestions.getValue().equals(orderType)) {
            String msgTitle = "拍照提问，已接受答后通知";
            String msgContent = "您已接受了拍照提问学霸答案，可对学霸进行评价！感谢您使用留同学APP";
            MsgReceive msgReceive = msgReceiveService.sendMsgReceiveNotice(BusOrder.class.getSimpleName(), userId, msgTitle, msgContent);
            orderPushMessage(msgReceive, msgTitle, msgContent);
        }
        if (OrderTypeEnum.HomeWork.getValue().equals(orderType)) {
            String msgTitle = "作业无忧，已接受答后通知";
            String msgContent = "您已接受了作业无忧学霸答案，可对学霸进行评价！感谢您使用留同学APP";
            MsgReceive msgReceive = msgReceiveService.sendMsgReceiveNotice(BusOrder.class.getSimpleName(), userId, msgTitle, msgContent);
            orderPushMessage(msgReceive, msgTitle, msgContent);
        }
    }

    private void acceptAnswerSendAnswerUserMessage(Integer orderType, Long answerUserId, Long userId) {
        String nickName = "";
        AppUser appUser = appUserService.getUserById(userId);
        if (FlymeUtils.isNotEmpty(appUser)) {
            nickName = appUser.getNickName();
        }
        if (OrderTypeEnum.TakePhotosAskQuestions.getValue().equals(orderType)) {
            String msgTitle = "拍照提问，学霸采纳通知";
            String msgContent = "恭喜您！上传的拍照提问解答，【" + nickName + "】已经确认接受答案！感谢您使用留同学APP";
            MsgReceive msgReceive = msgReceiveService.sendMsgReceiveNotice(BusOrder.class.getSimpleName(), answerUserId, msgTitle, msgContent);
            orderPushMessage(msgReceive, msgTitle, msgContent);
        }
        if (OrderTypeEnum.HomeWork.getValue().equals(orderType)) {
            String msgTitle = "作业无忧，学霸采纳通知";
            String msgContent = "恭喜您！上传作业无忧解答，【" + nickName + "】已经确认接受答案！感谢您使用留同学APP";
            MsgReceive msgReceive = msgReceiveService.sendMsgReceiveNotice(BusOrder.class.getSimpleName(), answerUserId, msgTitle, msgContent);
            orderPushMessage(msgReceive, msgTitle, msgContent);
        }
    }

    @Override
    public boolean updateOrderState(Long orderId, String orderState) {
        CriteriaUpdate cu = new CriteriaUpdate();
        cu.set("orderState", orderState);
        cu.eq(true, "orderId", orderId);
        return update(cu);
    }

    @Override
    public boolean updatePayState(Long orderId, Integer payState) {
        CriteriaUpdate cu = new CriteriaUpdate();
        cu.set("payState", payState);
        cu.eq(true, "orderId", orderId);
        return update(cu);
    }

    @Override
    public ResultBody getOrderAnswerId(Long orderId) {
        CriteriaQuery cq = new CriteriaQuery(BusOrderAnswer.class);
        cq.eq(true, "orderId", orderId);
        cq.eq("isAnswer", 1);
        BusOrderAnswer busOrderAnswer = busOrderAnswerService.getOne(cq);
        EntityMap entityMap = new EntityMap();
        entityMap.put("answerId", "");
        if (FlymeUtils.isNotEmpty(busOrderAnswer)) {
            entityMap.put("answerId", busOrderAnswer.getAnswerId());
        }
        return ResultBody.ok(entityMap);
    }

    @Override
    public BusOrder findByOrderNo(String outTradeNo) {
        CriteriaQuery cq = new CriteriaQuery(BusOrderAnswer.class);
        cq.eq(true, "orderNo", outTradeNo);
        return getOne(cq);
    }

    @Override
    public Long countAnswerIngNum(Long answerUserId) {
        CriteriaQuery cq = new CriteriaQuery(BusOrderAnswer.class);
        cq.eq(true, "answerUserId", answerUserId);
        cq.eq("payState", PayStateEnum.HavePay.getValue());
        cq.in("orderState", Arrays.asList("2", "P3", "Z3"));
        return count(cq);
    }

    @Override
    public ResultBody getEnterClassRoomInfo(Long orderId) {
        Long userId = OpenHelper.getUserId();
        BusOrder busOrder = getById(orderId);
        //学霸id
        Long answerUserId = busOrder.getAnswerUserId();
        if (FlymeUtils.isEmpty(busOrder)) {
            return ResultBody.failed("订单不存在");
        }
       /* Integer orderType = busOrder.getOrderType();
        if (!orderType.equals(OrderTypeEnum.BookingTutoring.getValue())) {
            return ResultBody.failed("只有预约辅导订单才能进入课堂上课");
        }*/
        String userName = OpenHelper.getUserName();
        String appId = agoraProperties.getAppId();
        String rtmToken = rtmTokenBuilderUtil.getRtmToken(String.valueOf(userId), 3600 * 24);
        if (userId.equals(answerUserId)) {
            updateOrderState(orderId, OrderStateYEnum.OrderState3.getValue());
        }
        EntityMap data = new EntityMap();
        data.put("orderId", orderId);
        data.put("userId", userId);
        data.put("rtmToken", rtmToken);
        data.put("userName", userName);
        data.put("appId", appId);
        return ResultBody.ok(data);
    }

    @Override
    public void orderPushMessage(MsgReceive msgReceive, String msgTitle, String msgContent) {
        Long receiveUserId = msgReceive.getReceiveUserId();
        AppUser appUser = appUserService.getUserById(receiveUserId);
        Integer pushOrderMsg = FlymeUtils.getInteger(appUser.getPushOrderMsg(), 0);
        log.info("支付成功回调发送消息orderPushMessage" + pushOrderMsg);
        if (pushOrderMsg == 1) {
            log.info("支付成功回调发送消息orderPushMessage正确");
            EntityMap extra = new EntityMap();
            extra.put("msgType", BusOrder.class.getSimpleName());
            extra.put("msgUserId", msgReceive.getMsgUserId());
            log.info("支付成功回调发送消息receiveUserId"+TypeUtils.castToString(receiveUserId));
            int result = jPushService.sendByDeviceToken(TypeUtils.castToString(receiveUserId), msgTitle, msgTitle, msgContent, extra);
            log.info("支付成功回调发送消息结果"+result);
            log.info("支付成功回调发送消息orderPushMessage执行完");
        }
    }

    @Override
    public BigDecimal sumPayableAmountByPayState(Integer payState) {
        CriteriaQuery cq = new CriteriaQuery(BusOrder.class);
        cq.addSelect("COALESCE(sum(payableAmount),0) amount");
        cq.eq("payState", payState);
        EntityMap one = findOne(cq);
        BigDecimal amount = one.getBigDecimal("amount");
        return amount;
    }

    @Override
    public BigDecimal sumOrderAmountByPayState(Integer payState) {
        CriteriaQuery cq = new CriteriaQuery(BusOrder.class);
        cq.addSelect("COALESCE(sum(orderAmount),0) amount");
        cq.eq("payState", payState);
        EntityMap one = findOne(cq);
        BigDecimal amount = one.getBigDecimal("amount");
        return amount;
    }

    @Override
    public BigDecimal sumOrderAmountByPayState(Integer payState, Integer dateType, String date) {
        CriteriaQuery cq = new CriteriaQuery(BusOrder.class);
        cq.addSelect("COALESCE(sum(orderAmount),0) amount");
        cq.eq("payState", payState);
        if (dateType == 1) {
            cq.eq("DATE_FORMAT(createTime,'%Y-%m-%d')", date);
        }
        if (dateType == 2) {
            cq.eq("DATE_FORMAT(createTime,'%Y-%m')", date);
        }
        if (dateType == 3) {
            cq.eq("DATE_FORMAT(createTime,'%Y')", date);
        }
        EntityMap one = findOne(cq);
        BigDecimal amount = one.getBigDecimal("amount");
        return amount;
    }

    @Override
    public BigDecimal sumUserCommission(Long userId) {
        CriteriaQuery cq = new CriteriaQuery(BusOrder.class);
        cq.addSelect("COALESCE(sum(commission),0) commissionAmount");
        cq.eq("answerUserId", userId);
        cq.eq("payState", PayStateEnum.HavePay.getValue());
        cq.eq("orderState", "5");
        EntityMap one = findOne(cq);
        BigDecimal amount = one.getBigDecimal("commissionAmount");
        return amount;
    }

    @Override
    public BigDecimal totalTodayCommission(Long userId, String date) {
        CriteriaQuery cq = new CriteriaQuery(BusOrder.class);
        cq.addSelect("COALESCE(sum(commission),0) commissionAmount");
        cq.eq("answerUserId", userId);
        cq.eq("DATE_FORMAT(createTime,'%Y-%m-%d')", date);
        cq.eq("payState", PayStateEnum.HavePay.getValue());
        cq.eq("orderState", "5");
        EntityMap one = findOne(cq);
        BigDecimal amount = one.getBigDecimal("commissionAmount");
        return amount;
    }

    @Override
    public void orderBookingTutoringCancel(BusOrder busOrder, String title, String cause) {
        Long orderId = busOrder.getOrderId();
        BigDecimal payableAmount = busOrder.getPayableAmount();
        String orderNo = busOrder.getOrderNo();
        Long userId = busOrder.getUserId();
        if (FlymeUtils.isNotEmpty(busOrder)) {
            //查询支付流水
            PayInfo payInfo = payInfoService.findByOutTradeNo(orderNo);
            String payType = payInfo.getPayType();
            //留币余额支付
            if (payType.equals(PayTypeEnum.LiuBi.getValue())) {
                String body = cause + ",退款金额为" + payableAmount;
                boolean b = payBalanceService.addBindAmount(userId, userId, payableAmount, BalanceLogTypeEnum.logType5.getValue(), title, body);
                if (b) {
                    //修改支付流水为已退款
                    payInfo.setPayStatus(PayStatusEnum.refund.code);
                    payInfo.setReturnDate(DateUtils.getDateTime());
                    payInfo.setReturnAmount(payableAmount);
                    payInfo.setReason(title);
                    payInfoService.updateById(payInfo);
                    //修改订单状态为已取消
                    updateOrderState(orderId, "0");
                }
            }
            //微信支付
            if (payType.equals(PayTypeEnum.WeiXin.getValue())) {
                PayConfig payConfig = payConfigService.getByProperty("payType", payType);
                PayResponse payResponse = payConfigService.getPayResponse(payConfig.getPayId(), "");
                RefundOrder refundOrder = new RefundOrder();
                refundOrder.setRefundNo(IdWorker.getIdStr());
                refundOrder.setOutTradeNo(orderNo);
                refundOrder.setOrderDate(DateUtils.getNowDate());
                refundOrder.setRefundAmount(payableAmount);
                refundOrder.setTotalAmount(payableAmount);
                Map refund = payResponse.getService().refund(refundOrder);
                System.out.println(refund.toString());
                String result_code = (String) refund.get("result_code");
                if (result_code.equals("SUCCESS")) {
                    //修改支付流水为已退款
                    payInfo.setPayStatus(PayStatusEnum.refund.code);
                    payInfo.setReturnAmount(payableAmount);
                    payInfo.setReturnDate(DateUtils.getDateTime());
                    payInfo.setReason(title);
                    payInfoService.updateById(payInfo);
                    //修改订单状态为已退款
                    updateOrderState(orderId, "0");
                    updatePayState(orderId, PayStateEnum.refund.getValue());
                }
            }
        }
    }

    @Override
    public Long totalOrder(Long userId) {
        CriteriaQuery cq = new CriteriaQuery(BusOrder.class);
        cq.eq("userId", userId);
        cq.in("orderState", "Y1", "Y2", "Y3", "Y4", "P1", "2", "P3", "P4", "Z1", "Z3", "Z4");
        return count(cq);
    }


    @Override
    public void afterGet(CriteriaQuery cq, EntityMap result) {
        commonGetOrderDetails(result);
    }

    /**
     * 公共详情部分
     */
    private void commonGetOrderDetails(EntityMap map) {
        //处理专业,专业标签
        String subjectIds = map.get("subjectIds");
        Long orderId = map.getLong("orderId");
        Integer orderType = map.getInt("orderType");
        //返回学霸信息
        Long answerUserId = map.getLong("answerUserId");
        String orderTypeDesc = getOrderTypeDesc(orderType);
        List<String> fileIds = new ArrayList<>();
        List<String> imgFileIds = new ArrayList<>();
        map.put("orderTypeDesc", orderTypeDesc);
        List<String> subjectTitles = busSubjectService.selectSubjectTitles(subjectIds);
        map.put("subjectTitles", subjectTitles);
        List<EntityMap> imgFileList = sysFileService.selectFileListLikeFileType(orderId, BusOrder.class.getSimpleName(), "image");
        map.put("imgFileList", imgFileList);
        for (EntityMap entityMap : imgFileList) {
            imgFileIds.add(entityMap.get("fileId"));
        }
        List<EntityMap> otherFileList = sysFileService.selectFileListNotLikeFileType(orderId, BusOrder.class.getSimpleName(), "image");
        for (EntityMap entityMap : otherFileList) {
            fileIds.add(entityMap.get("fileId"));
        }
        map.put("otherFileList", otherFileList);
        map.put("fileIds", ConvertUtils.listToString(fileIds));
        map.put("imgFileIds", ConvertUtils.listToString(imgFileIds));
        if (FlymeUtils.isNotEmpty(answerUserId)) {
            EntityMap answerUserInfo = busScholartyrantService.getScholartyrantInfo(answerUserId);
            String xbSubjectIds = answerUserInfo.get("subjectInfo");
            List<String> xbSubjectTitles = busSubjectService.selectSubjectTitles(xbSubjectIds);
            answerUserInfo.put("subjectTitles", ConvertUtils.listToString(xbSubjectTitles));
            map.put("answerUserInfo", answerUserInfo);
        }
        //拼接辅导类型
        if (OrderTypeEnum.BookingTutoring.getValue().equals(orderType)) {
            Long tutorTypeId = map.getLong("tutorTypeId");
            if (FlymeUtils.isNotEmpty(tutorTypeId)) {
                BusTutorType tutorType = busTutorTypeService.getById(tutorTypeId);
                BigDecimal tutorPrice = tutorType.getTutorPrice();
                BigDecimal durationTime = map.get("durationTime");
                String tutorTypeName = tutorType.getTutorTypeName();
                Integer chargeType = tutorType.getChargeType();
                String priceUnit = tutorType.getPriceUnit();
                String tutorTitle = MessageFormat.format("{0}(${1}/{2})", tutorTypeName, tutorPrice, priceUnit);
                map.put("tutorTitle", tutorTitle);
                if (chargeType.equals(1)) {
                    durationTime = durationTime.setScale(1);
                }
                map.put("durationTime", durationTime);
                map.put("priceUnit", priceUnit);
                map.put("tutorTypeId", tutorType.getTutorTypeId());
                map.put("tutorTypeName", tutorTypeName);
                map.put("tutorPrice", tutorPrice);
                map.put("chargeType", chargeType);
            }
        }
    }
}
